package com.xingxue.config;

import com.xingxue.entity.User;
import com.xingxue.mapper.UserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.ProviderManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.annotation.SecurityBuilder;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.ExceptionMappingAuthenticationFailureHandler;
import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

import javax.servlet.Filter;
import javax.servlet.http.HttpServletRequest;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

@Configuration
@EnableWebSecurity(debug = true)
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .antMatchers("/css/**", "/js/**", "/img/**", "/403.html", "/404.html", "/500.html").permitAll()
                .antMatchers("/system/**", "/order/**", "/product/**").access("authenticated and @checkService.check(authentication, request)")
                .anyRequest().authenticated()
        .and()
                .formLogin().loginPage("/login").failureUrl("/login?error").permitAll()
        .and()
                .csrf()
        .and()
                .addFilterAt(customFilter(), UsernamePasswordAuthenticationFilter.class);
    }

    @Autowired
    private UserMapper userMapper;

    @Bean
    @Override
    public UserDetailsService userDetailsService(){
        return username -> {
            User user = userMapper.findUserWithRoleAndModuleAndOrg(username);
            if(user == null) {
                throw new UsernameNotFoundException("用户不存在！");
            }
            return user;
        };
    }

    @Bean
    public AuthenticationManager authenticationManager() {
        DaoAuthenticationProvider provider = new DaoAuthenticationProvider() {
            @Override
            public Authentication authenticate(Authentication authentication) throws AuthenticationException {
                System.out.println("enter...customProvider");
                UsernamePasswordAuthenticationToken token = (UsernamePasswordAuthenticationToken) authentication;
                CaptchaToken captchaToken = (CaptchaToken) token.getDetails();
                System.out.println("token:" + captchaToken.getCaptcha());
                if (!"123".equals(captchaToken.getCaptcha())) {
                    throw new CaptchaException("错误的验证码!");
                }
                return super.authenticate(authentication);
            }
        };
        provider.setUserDetailsService(userDetailsService());
        provider.setPasswordEncoder(new BCryptPasswordEncoder(4));
        ProviderManager manager = new ProviderManager(Arrays.asList(provider));
        return manager;
    }


    @Bean
    public Filter customFilter() {
        UsernamePasswordAuthenticationFilter filter = new UsernamePasswordAuthenticationFilter() {
            @Override
            protected void setDetails(HttpServletRequest request, UsernamePasswordAuthenticationToken authRequest) {
                System.out.println("enter...customFilter");
                String captcha = request.getParameter("captcha");
                CaptchaToken token = new CaptchaToken(captcha);
                authRequest.setDetails(token);
            }
        };
        filter.setAuthenticationManager(authenticationManager());
        filter.setAuthenticationFailureHandler(new SimpleUrlAuthenticationFailureHandler("/login?error"));
        return filter;
    }

}
